home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung 2 / Power-Programmierung CD 2 (Tewi)(1994).iso / c / tools / make / nmake / reader.c < prev    next >
Encoding:
C/C++ Source or Header  |  1987-07-21  |  13.4 KB  |  491 lines

  1. /* read the makefile, and generate the linked lists */
  2. #include <stdio.h>
  3. #include "make.h"
  4.  
  5. #if MSC
  6. #include <ctype.h>
  7. #endif
  8.  
  9. #define DONE 1
  10. #define ADEFN 2
  11. #define ARULE 3
  12. #define AMACRO 4
  13.  
  14. #if LC
  15. extern int _stack;
  16. #endif
  17.  
  18. /* externals, all defined in make.c */
  19. extern struct macrec *maclist;
  20. extern struct defnrec *defnlist;
  21. extern struct llist *dolist;
  22. extern struct rulerec *rulelist;
  23. extern int no_file,linecont;
  24. long getmodified();
  25. char *get_mem(),*mov_in();
  26.  
  27.  
  28.  
  29. /* local variables */
  30. FILE *fil;
  31. char *fword,*restline,line[INMAX],backup[INMAX];
  32. char *frule;
  33. struct llist *fhowto,*howp3;
  34. struct llist *fdeps,*deprec3;
  35. struct macrec *macp,*macp2;
  36. struct rulerec *rulep,*rulep2;
  37. struct defnrec *defnp;
  38. int sending,def_ready,gdone,rule_send,rule_ready;
  39. struct llist  *targ,*q_how,*q_dep,*targ2;
  40.  
  41. readmakefile(s)
  42. char *s;
  43. {
  44. int i,k;
  45.  
  46.     /* open the file */
  47.     if ( strcmp(s,"-") == 0 ) fil = stdin;
  48.     else if ( (fil = fopen(s,"r")) == NULL) {
  49.     error("couldn't open '%s'.",s);
  50.     return;
  51.     }
  52.  
  53.  
  54.     /* initialise getnxt() */
  55.     sending = def_ready = gdone = rule_send = rule_ready = FALSE;
  56.     targ = q_how = q_dep = NULL;
  57.     if (getline(fil, backup) == FALSE)
  58.        panic("Empty Makefile");
  59.  
  60.  
  61.     /* getnxt() parses the next line, and returns the parts */
  62.     while (TRUE) switch( getnxt() ){
  63.  
  64.     case DONE: return;
  65.  
  66.     case AMACRO:      /* add a macro to the list */
  67.  
  68.         /** get space */
  69.         macp = (struct macrec *)get_mem((unsigned) sizeof(struct macrec));
  70.         if (maclist == NULL)
  71.             maclist = macp;
  72.         else {
  73.             macp2 = maclist;
  74.             while (macp2->nextmac != NULL)
  75.                  macp2 = macp2->nextmac;
  76.             macp2->nextmac = macp;
  77.          }
  78.          uppercase(fword);
  79.          macp->name = mov_in(fword);
  80.          macp->mexpand = mov_in(restline);
  81.          macp->nextmac = NULL;
  82.          break;
  83.  
  84.     case ARULE:      /* add a rule to the list */
  85.  
  86.         rulep = (struct rulerec *)get_mem(sizeof(struct rulerec));
  87.         if (rulelist == NULL)
  88.             rulelist = rulep;
  89.         else{
  90.             rulep2 = rulelist;
  91.             while (rulep2->nextrule != NULL)
  92.                rulep2 = rulep2->nextrule;
  93.             rulep2->nextrule = rulep;
  94.         }
  95.         /*fword[0] is defined to be a period*/
  96.         for (i=1; notnull(fword[i]) ;i++)
  97.             if ( fword[i] == '.' ) break;
  98.         if ( i == strlen(fword) )  panic("Bad rule '%s'",fword);
  99.         fword[i] = NUL;
  100.         rulep->dep = mov_in(fword + 1); /*don't save the preceding '.' */
  101.         /* be sure object extension has no spaces */
  102.         for ( k = i+1 ; notnull(fword[k]) && !isspace(fword[k]) ; k++ )
  103.         ;/*NOP*/
  104.         if ( isspace(fword[k]) ) fword[k] = NUL;
  105.         rulep->targ = mov_in(fword + i + 1);
  106.         rulep->rule = fhowto;
  107.         rulep->nextrule = NULL;
  108.         break;
  109.  
  110.     case ADEFN:     /* add a definition */
  111.  
  112.         if (no_file) {      /*if no target specified on command line... */
  113.             add_do(fword);  /*push this target on to do list */
  114.             no_file = FALSE;
  115.         }
  116.         /* getnxt() returns target ( fword ) , pointer to expanded howto
  117.            list ( fhowto ) and pointer to expanded depends ( fdeps )
  118.         */
  119.         if ( defnlist == NULL ) {
  120.             add_defn();   /* add the current definition to the end */
  121.     }
  122.         else {
  123.             defnp = defnlist;
  124.             while ( defnp != NULL ) {
  125.                 if (strcmp(defnp->name,fword) == 0) break;
  126.                 else defnp = defnp->nextdefn;
  127.         }
  128.             if ( defnp == NULL ) {
  129.                 /* target not currently in list */
  130.                 add_defn();
  131.         }
  132.             else {
  133.                 /* target is on list, add new depends and howtos */
  134.                 if (defnp->dependson == NULL)
  135.                     defnp->dependson = fdeps;
  136.                 else {
  137.                     deprec3 = defnp->dependson;
  138.                     while (deprec3->next != NULL)
  139.                          deprec3 = deprec3->next;
  140.                     deprec3->next = fdeps;
  141.         }
  142.                 /* add new howtos */
  143.                 if (defnp->howto == NULL)
  144.                     defnp->howto = fhowto;
  145.                 else {
  146.                     howp3 = defnp->howto;
  147.                     while ( howp3->next != NULL)
  148.                          howp3 = howp3->next;
  149.                     howp3->next = fhowto;
  150.         }
  151.         }
  152.     }
  153.         break;
  154.     }
  155. }
  156.  
  157. add_defn()     /* add a new definition */
  158. {
  159. struct defnrec *ptr,*ptr2;
  160.     ptr = (struct defnrec *)get_mem(sizeof(struct defnrec));
  161.     ptr->name = fword;
  162.     ptr->uptodate = FALSE;
  163.     ptr->modified = getmodified(fword,DEPENDANT);
  164.     ptr->dependson = fdeps;
  165.     ptr->howto = fhowto;
  166.     ptr->nextdefn = NULL;
  167.     if ( defnlist == NULL ) {
  168.     defnlist = ptr;
  169.     return;
  170.     }
  171.     else {
  172.     ptr2 = defnlist;
  173.     while ( ptr2->nextdefn != NULL )
  174.             ptr2 = ptr2->nextdefn;
  175.     ptr2->nextdefn = ptr;
  176.     }
  177. }
  178.  
  179. getnxt()
  180. {
  181. int pos,mark,parsed;
  182. char exp_line[INMAX];
  183. struct llist *mkllist(),*mkexphow(),*mkexpdep(),*q_how2,*q_how3;
  184.  
  185.   while ( TRUE ) {
  186.  
  187.    /* if we are currently sending targets */
  188.    if ( sending ) {
  189.         if ( targ2->next == NULL) {
  190.             sending = def_ready = FALSE;
  191.         }
  192.         fword = mov_in(targ2->name);
  193.         fhowto = mkexphow(q_how,targ2->name,REPT_ERR);
  194.         fdeps = mkexpdep(q_dep,targ2->name);
  195.         targ2 = targ2->next;
  196.         return ( ADEFN );
  197.     }
  198.     
  199.     /* are we sending a rule? */
  200.     if ( rule_send ) {
  201.         fword = frule;
  202.         fhowto = mkexphow(q_how,(char *)NULL,IGN_ERR); /* target == NULL -> don't expand */
  203.         rule_send = rule_ready = FALSE;
  204.         return( ARULE );
  205.     }
  206.     
  207.     if ( gdone ) return ( DONE );
  208.     /* if we are not currently sending... */
  209.  
  210.     /* load the next line into 'line' ( which may be backed-up ) */
  211.     if ( backup[0] != NUL ) {
  212.         strcpy(line,backup);
  213.         backup[0] = NUL;
  214.     }
  215.     else {
  216.         if ( getline(fil,line) == FALSE ) {
  217.             if ( def_ready ) sending = TRUE;
  218.             if ( rule_ready ) rule_send = TRUE;
  219.             gdone = TRUE;
  220.             continue;  /* break the loop, and flush any definitions */
  221.         }
  222.     }
  223.     parsed = FALSE;
  224.  
  225.     /* check for rule, and begin loading it if there */
  226.     if (line[0] == '.'){
  227.         /* found a rule */
  228.         for (pos = 0 ; line[pos] != ':' && notnull(line[pos]) ; pos++)
  229.             if (isspace(line[pos])) continue;
  230.         if (isnull(line[pos]))
  231.            error("rule needs colon separator '%s'",line);
  232.         mark = pos;
  233.         for (pos++ ; line[pos] != ';' && notnull(line[pos]) ; pos++) ;
  234.         if (isnull(line[pos]))
  235.            error("rule needs ';' after ':'-- '%s'",line);
  236.         parsed = TRUE;
  237.         if ( rule_ready || def_ready ) {
  238.             if ( def_ready ) sending = TRUE;
  239.             else rule_send = TRUE;
  240.             strcpy(backup,line); /* push this line, and send what we already have */
  241.         }
  242.         else {
  243.             rule_ready = TRUE;
  244.             line[mark] = NUL;
  245.             frule = mov_in(line);
  246.             free_list(q_how);
  247.             q_how = MkListMem();
  248.             q_how->name = mov_in(line + pos + 1 );
  249.             q_how->next = NULL;
  250.         }
  251.     }
  252.     
  253.     /* check for macro, and return it if there */
  254.     if ( !parsed ) {
  255.         pos = 0;
  256.         while ( line[pos] != '=' &&
  257.                 line[pos] != ':' &&
  258.                 !isspace(line[pos]) &&
  259.                 notnull(line[pos])) pos++;
  260.         mark = pos;
  261.         if (notnull(line[pos]) && line[pos] != ':'){
  262.             /* found a macro */
  263.             if (isspace(line[pos]))
  264.                while (isspace(line[pos]) && notnull(line[pos])) pos++;
  265.             if (isnull(line[pos]))
  266.                panic("bad macro or definition '%s'",line);
  267.             if ( line[pos] == '=' ) {
  268.                 /* found a macro */
  269.                 line[mark] = NUL;
  270.                 fword = line;
  271.                 mark = pos + 1;
  272.                 while ( isspace(line[mark]) ) mark++; /* skip spaces before macro starts */
  273.                 restline = line + mark;
  274.                 return ( AMACRO );
  275.             }
  276.         }
  277.     }
  278.  
  279.  
  280.  
  281.     /* check for and add howto line */
  282.     if ( isspace(line[0]) ) {
  283.     if (!def_ready && !rule_ready)
  284.        error("how-to line without preceeding definition or rule\n'%s'",line);
  285.     for ( pos = 0 ; isspace(line[pos]) ; pos++ ) ;
  286.     q_how2 = MkListMem();
  287.     if ( q_how == NULL ) {
  288.         q_how = q_how2;
  289.     }
  290.     else {
  291.         q_how3 = q_how;
  292.         while ( q_how3->next != NULL )
  293.                 q_how3 = q_how3->next;
  294.         q_how3->next = q_how2;
  295.     }
  296.     q_how2->name = mov_in(line);
  297.     q_how2->next = NULL;
  298.     parsed = TRUE;
  299.     }
  300.  
  301.     
  302.     /* check for definition */
  303.     if (!parsed) {
  304.         pos = 0;
  305.         while ( notnull(line[pos]) && line[pos] != ':') pos++;
  306.         if (line[pos] == ':') {
  307.             /* found a definition */
  308.             parsed = TRUE;
  309.             if (def_ready || rule_ready) {
  310.                 if ( def_ready ) sending = TRUE;
  311.                 else rule_send = TRUE;
  312.                 strcpy(backup,line);
  313.             }
  314.             else {
  315.                /* free up the space used by the previous lists */
  316.                free_list(targ);targ = NULL;
  317.                free_list(q_how);q_how = NULL;
  318.                free_list(q_dep);q_dep = NULL;
  319.                line[pos] = NUL;
  320.                expand(line,exp_line,"",NO_TARG);
  321.                targ2 = targ = mkllist(exp_line);
  322.                q_dep = mkllist(line + pos + 1);
  323.                def_ready = TRUE;
  324.             }
  325.         }
  326.     }
  327.     if (!parsed)
  328.        panic("unable to parse line '%s'",line);
  329.   }
  330. }
  331.  
  332.  
  333.     
  334. /*
  335.    load the next line from 'stream' to 'where' allowing for comment char
  336.    and line continuations 
  337. */
  338. getline(stream,where)
  339. char *where;
  340. FILE *stream;
  341. {
  342. int i,x;
  343.  
  344.     while (fgets(where,INMAX,stream) != NULL) {
  345.         i = strlen(where);
  346.         where[--i] = NUL;  /* null terminate the string ( drop \n ) */
  347.  
  348.         /* terminate stdin input with a '.' */
  349.         if ( (stream == stdin) && (strcmp(where,".") == 0) ) return( FALSE );
  350.  
  351.         /* if line is blank, or begins with # , skip it */
  352.         if (isnull(where[0]) || where[0] == '#')  continue;
  353.  
  354.         /* if the line is only ws, skip it */
  355.         for ( x = 0; isspace(where[x]) && notnull(where[x]) ; x++) ;
  356.         if (isnull(where[x])) continue;
  357.  
  358.         while (where[i-1] == linecont ){
  359.            /*continue reading line if line continuation character*/
  360.            if (fgets(where + i - 1,INMAX,stream) ==  NULL)
  361.                error("end of file before end of line");
  362.            if ( (stream == stdin) && (strcmp(where + i - 1,".\n") == 0) ) 
  363.                error("end of file before end of line");
  364.            i = strlen(where);
  365.            where[--i] = NUL;
  366.         }
  367.         if ( i >= INMAX ) {
  368.             where[INMAX] = NUL;
  369.             panic("line too long\n'%s'",where);
  370.         }
  371.         return ( TRUE );
  372.     }
  373.     return ( FALSE );
  374. }
  375.  
  376.  
  377.  
  378. struct llist *mkllist( s )  /* make a  linked list */
  379. char *s;
  380. {
  381. int i,pos;
  382. char lname[INMAX];
  383. struct llist *ptr,*ptr2,*retval;
  384.  
  385.  
  386.      i = pos = 0;
  387.      retval = NULL;
  388.      while ( TRUE ) {
  389.      while ( notnull(s[pos]) && isspace(s[pos]) ) pos++;
  390.  
  391.      if ( isnull(s[pos]) ) return( retval );
  392.  
  393.      while ( !isspace(s[pos]) && notnull(s[pos]) ) lname[i++] = s[pos++];
  394.  
  395.      /* found something to add */
  396.      ptr = MkListMem();
  397.      if ( retval == NULL ) {
  398.          retval = ptr;
  399.      }
  400.      else {
  401.          ptr2 = retval;
  402.          while ( ptr2->next != NULL )
  403.                  ptr2 = ptr2->next;
  404.          ptr2->next = ptr;
  405.      }
  406.      lname[i] = NUL;
  407.      ptr->name = mov_in(lname);
  408.      ptr->next = NULL;
  409.      i = 0;
  410.      }
  411. }
  412.  
  413.  
  414. struct llist *mkexphow(head,target,eflag) /* make an expanded linked list for how */
  415. struct llist *head;
  416. char *target;
  417. int eflag;
  418. {
  419. struct llist *p,*p2,*retval;
  420. char temp[INMAX];
  421.  
  422.    if ( head == NULL ) {
  423.        return ( NULL );
  424.    }
  425.  
  426.    retval = NULL;
  427.    while ( head != NULL ) {
  428.       
  429.       if ( target != NULL ) expand(head->name,temp,target,eflag);
  430.       else strcpy(temp,head->name);
  431.       p = MkListMem();      
  432.       p->name = mov_in(temp);
  433.       p->next = NULL;
  434.  
  435.       if ( retval == NULL ) retval = p;
  436.       else {
  437.       p2 = retval;
  438.       while ( p2->next != NULL )
  439.           p2 = p2->next;
  440.       p2->next = p;
  441.       }
  442.       head = head->next;
  443.    }
  444.    return( retval );
  445. }
  446.  
  447. struct llist *mkexpdep(head,target)  /* make an expanded linked list for dep*/
  448. struct llist *head;
  449. char *target;
  450. {
  451. struct llist *p,*p2,*p3,*retval;
  452. char temp[INMAX];
  453.  
  454.  if ( head == NULL ) {
  455.       return ( NULL );
  456.  }
  457.  
  458.  retval = NULL;
  459.  while ( head != NULL ) {
  460.       
  461.    expand(head->name,temp,target,REPT_ERR);
  462.    p3 = mkllist(temp);
  463.    while ( p3 != NULL ) {
  464.       p = MkListMem();      
  465.       p->name = mov_in(p3->name);
  466.       p->next = NULL;
  467.  
  468.       if ( retval == NULL ) retval = p;
  469.       else {
  470.       p2 = retval;
  471.       while ( p2->next != NULL )
  472.           p2 = p2->next;
  473.       p2->next = p;
  474.       }
  475.       p3 = p3->next;
  476.    }
  477.    free_list(p3);
  478.    head = head->next;
  479.  }
  480.  return( retval );
  481. }
  482.  
  483.  
  484. free_list(ptr)   /* kill a linked list */
  485. struct llist *ptr;
  486. {
  487.     if       ( ptr == NULL )       return;
  488.     else if  ( ptr->next == NULL ) free(ptr);
  489.     else                           free_list(ptr->next);
  490. }
  491.     
  492.